import cv2, imutils
import time
import pyzbar.pyzbar as pyzbar
import numpy as np

# 裁剪
# 宽度是x 顶点向右方向  高度是y ,顶点向下方向
crop_x_min = 0   
crop_x_max = 1000
crop_y_min = 590   
crop_y_max = 1890

kernel_2 = np.ones((2, 2), np.uint8)  # 2x2的卷积核
kernel_3 = np.ones((3, 3), np.uint8)  # 3x3的卷积核
kernel_4 = np.ones((4, 4), np.uint8)  # 4x4的卷积核

Lower_black = np.array([70, 100, 100])
Upper_black = np.array([87, 150, 120])
draw_black = (0,0,0)
black = [Lower_black, Upper_black, 'black',draw_black]

class frameClass:

    def detect(self, c):
        # 初始化形状名和近似的轮廓
        shape = "unidentified"
        shape_flag = 0
        peri = cv2.arcLength(c, True)
        approx = cv2.approxPolyDP(c, 0.04 * peri, True)

        # 如果当前的轮廓含有3条折线，则其为三角形
        if len(approx) == 3:
            shape = "triangle"
            shape_flag = 3
        # 如果当前的轮廓含有4条折线，则其可能是矩形或者正方形
        elif len(approx) == 4:
            # 获取轮廓的边界框并计算长和宽的比例
            (x, y, w, h) = cv2.boundingRect(approx)
            ar = w / float(h)
            shape = "square" if ar >= 0.95 and ar <= 1.05 else "rectangle"
            shape_flag = 4
        # 如果这个轮廓含有5条折线，则它是一个多边形
        elif len(approx) == 5:
            shape = "pentagon"
            shape_flag = 5
        # 否则的话，我们认为它是一个圆
        else:
            shape = "circle"
            shape_flag = 1

        # 返回形状的名称
        return shape,shape_flag

    def detect_shape(self,img):
        max_area = 30000
        min_area = 3000
        # 进行高斯模糊操作
        blurred = cv2.GaussianBlur(img, (5, 5), 0)
        # 进行图片灰度化
        gray = cv2.cvtColor(blurred, cv2.COLOR_BGR2GRAY)
        # 进行颜色空间的变换
        lab = cv2.cvtColor(blurred, cv2.COLOR_BGR2LAB)
        # 进行阈值分割
        thresh = cv2.threshold(gray, 60, 255, cv2.THRESH_BINARY)[1]
        thresh_show = cv2.resize(thresh, (1020,560))
        cv2.imshow("Thresh", thresh_show)

        # 在二值图片中寻找轮廓
        cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
        cnts = imutils.grab_contours(cnts)

        cir_point={}

        # 遍历每一个轮廓
        i= 0
        for c in cnts:
            contour_area = cv2.contourArea(c)
            if contour_area > min_area and contour_area < max_area:
                # 计算每一个轮廓的中心点
                M = cv2.moments(c)
                if M["m00"] == 0:
                    continue
                cX = int(M["m10"] / M["m00"])
                cY = int(M["m01"] / M["m00"])

                # 进行颜色检测
                shape,shape_falg = self.detect(c)

                # 进行坐标变换
                c = c.astype("float")
                c = c.astype("int")
                # 进行坐标变换
                text = "{}".format(shape)
                # 绘制轮廓并显示结果
                cv2.drawContours(self.frame, [c], -1, (0, 255, 0), 2)
                cv2.putText(self.frame, text, (cX-10, cY-10), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 255), 2)

        return cir_point
    
    def run(self,):
        #### 通过CV库函数获取视频流数据
        cap = cv2.VideoCapture(0,)
        cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc('M', 'J', 'P', 'G'))  

        while True:  
            ret, self.frame = cap.read()  
            if not ret:
                time.sleep(0.1)
                #### 图像一旦获取失败，不断循环获取图像
                cap = cv2.VideoCapture(0,)
                cap.set(cv2.CAP_PROP_FOURCC,cv2.VideoWriter_fourcc('M','J','P','G'))  
                print("Can't to capture from camera. Exiting ...")  
                break  
            
            #### 图像裁剪--感兴趣区域进行检测
            # crop = np.zeros([1944,2592,3],np.uint8)
            # crop[crop_x_min:crop_x_max,crop_y_min:crop_y_max] = self.frame[crop_x_min:crop_x_max,crop_y_min:crop_y_max]
            crop = self.frame[crop_x_min:crop_x_max,crop_y_min:crop_y_max]
            img = crop
            
            #### 二维码检测
            self.detect_shape(img)
            time.sleep(0.01)
            
            #### 图像显示与保存
            img_show = cv2.resize(self.frame, (1020,560))
            cv2.imshow('frame', img_show)
            cv2.imwrite(f"crop.png",img)
            cv2.imwrite(f"frame.png",self.frame)
        
            # 按下'q'键退出循环  
            if cv2.waitKey(1) & 0xFF == ord('q'):  
                break  

        # 释放摄像头资源  
        cap.release()  
        # 关闭所有OpenCV窗口  
        cv2.destroyAllWindows()

a = frameClass()
a.run()    
    
